package com.lamatek.tags.google;

import java.util.StringTokenizer;
import java.util.Vector;

import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;

/**
 * GoogleMapInsertTag
 * 
 * Represents a &lt;googlemaps:insert> tag, which attaches a pannable, zoomable image
 * to the map. Developers should now extend this class or override it's methods.
 * 
 * @author Tom Cole
 * @version 0.96
 */
public class GoogleMapInsertTag extends TagSupport {

    String id;
    String point;
    String url;
    int baseZoom;
    int width;
    int height;
    Vector maps = null;
    String mapTypes = null;
    /**
     * Sets a map unique id for this insert. 
     * 
     * @param id A unique identifier for this insert.
     */
    public void setId(String id) {
        this.id = id;
    }
    /**
     * Returns the unique id for this insert.
     * 
     * @return The inserts id.
     */
    public String getId() {
        return id;
    }
    /**
     * Returns the zoom level at which this image should be displayed at
     * fullscale. The image will be scaled smaller/larger as the zoom 
     * level goes above/below this value.
     * 
     * @return The base zoom level for this image.
     */
    public int getBaseZoom() {
        return baseZoom;
    }
    /**
     * Sets the base zoom level where the image should be displayed
     * at full scale.
     * 
     * @param baseZoom The zoom level this image is displayed at full scale.
     */
    public void setBaseZoom(int baseZoom) {
        this.baseZoom = baseZoom;
    }
    /**
     * Returns the full scale height (in pixels) of this image.
     * 
     * @return The height of the image in pixels.
     */
    public int getHeight() {
        return height;
    }
    /**
     * Sets the full scale height (in pixels) of this image.
     * 
     * @param height The height of the image, in pixels.
     */
    public void setHeight(int height) {
        this.height = height;
    }
    /**
     * Returns the id of the point tag that points to the centerpoint of this image.
     * 
     * @return The id of a point tag in this map.
     */
    public String getPoint() {
        return point;
    }
    /**
     * Sets the id of the point tag that points to the centerpoing of this image.
     * The image will be placed on the map based on the longitude/latitude of this point.
     * 
     * @param point The id of a point that is part of this map.
     */
    public void setPoint(String point) {
        this.point = point;
    }
    /**
     * Returns the url to the image to attach to the map.
     * 
     * @return A relative or absolute url.
     */
    public String getUrl() {
        return url;
    }
    /**
     * Sets the url to the image that is to be attached to the map. This may be
     * either a relative or absolute url.
     * 
     * @param url A relative or asolute url to a valid image file.
     */
    public void setUrl(String url) {
        this.url = url;
    }
    /**
     * Returns the full scale width (in pixels) of this image.
     * 
     * @return The width of the image, in pixels.
     */
    public int getWidth() {
        return width;
    }
    /**
     * Sets the full scale width (in pixels) of this image.
     * 
     * @param width The full-scale width of the image, in pixels.
     */
    public void setWidth(int width) {
        this.width = width;
    }
    /**
     * Overrides doStartTag() in TagSupport. Developers should not override this method. 
     * If they do, they must call super.doStartTag() to ensure the tag get added to the
     * tree properly.
     */
    public int doStartTag() {
        Tag tag = this;
        while (tag.getParent() != null) {
            if (tag.getParent() instanceof GoogleMapTag) {
                ((GoogleMapTag) tag.getParent()).addInsert(this);
                return SKIP_BODY;
            }
            tag = tag.getParent();
        }
        return SKIP_BODY;
    }
    /**
     * Adds a map type to the allowed list. The mapType parameter should correspond to
     * the labels on the map type control buttons, and these are <em>case sensitive</em>.
     * For example, use "Map", "Hybrid" or "Satellite" for the default map types.
     * 
     * @param mapType A map type that should display this image insert.
     */
    public void addMapType(String mapType) {
        if (maps == null)
            maps = new Vector();
        maps.addElement(mapType);
    }
    /**
     * Sets the map types that should display this image insert. The mapTypes attribute
     * must be a comma separated list of map type names, as denoted by the map type control
     * buttons. For example, to display this image insert on all the standard map types you could
     * specify "Map, Hybrid, Satellite". The map type names are <em>case sensitive</em>.
     * <p>
     * If you specify no names (by not setting this or passing it 'null') then all
     * registered map types will display the image insert.
     * 
     * @param mapTypes A comma separated list of valid map type names.
     */
    public void setMapTypes(String mapTypes) {
        this.mapTypes = mapTypes;
        StringTokenizer t = new StringTokenizer(mapTypes, ",");
        while (t.hasMoreTokens()) {
            if (this.maps == null)
                this.maps = new Vector();
            String mapType = t.nextToken().trim();
            this.maps.addElement(mapType);
        }
    }
    /**
     * Returns the comma separated list of map type names that display this image insert.
     * This method only returns a value if map types were set using setMapTypes(), otherwise
     * it returns null.
     * 
     * @return The comma separated list of included map type names.
     */
    public String getMapTypes() {
       return mapTypes; 
    }
    /**
     * Returns the number of map type names that are to display this image insert, or 0 if there are none.
     * 
     * @return The number of map type names included.
     */
    public int getMapTypeCount() {
        if (maps == null)
            return 0;
        else
            return maps.size();
    }
    /**
     * Returns the map type name at the given interation, or null if none exists.
     * 
     * @return The registered map type name at the given iterator, or null of none is defined.
     */
    public String getMapType(int i) {
        if (maps == null)
            return null;
        else
            return (String) maps.elementAt(i);
    }
}
